# ===============================================================#
#                     Replication files for:                     #
#.  "Attitudinal and Behavioral Legacies of Wartime Violence:    #
#                      A Meta-Analysis"                          #
#                        Joan Barceló                            #
#               American Political Science Review                #
#               Last update: September 3, 2025                   #
# ===============================================================#

#################################
# Figure 4: Figure on Generalized Attitudinal Hardening
################################

## ------------------------ Setup ------------------------
library(tidyverse)
library(ggplot2)
library(patchwork)
library(grid)

# ---------- Paths and file maps ----------
base_path_meta    <- "~/Datasets/"
base_path_effects <- "~/Results/"

read_if <- function(path) if (file.exists(path)) read.csv(path) else NULL
lbl <- function(b, p) paste0(round(b, 2), ifelse(p < .001, "***", ifelse(p < .01, "**", ifelse(p < .05, "*", ""))))

col_full <- "indianred3"
col_biv  <- "steelblue4"
col_qe   <- "forestgreen"
sh_full  <- 15
sh_biv   <- 15
sh_qe    <- 17

## ------------------------ Load data ------------------------
# Political intolerance
meta.polintol        <- read_if(paste0(base_path_meta, "meta.political_intolerance.csv"))
meta.polintol_biv    <- read_if(paste0(base_path_meta, "meta.political_intolerance_biv.csv"))
polintol.effects     <- read_if(paste0(base_path_effects, "20.results_politicalintolerance_models.csv"))

# Social intolerance
meta.socintol        <- read_if(paste0(base_path_meta, "meta.social_intolerance.csv"))
meta.socintol.random <- read_if(paste0(base_path_meta, "meta.social_intolerance_random.csv"))
meta.socintol_biv    <- read_if(paste0(base_path_meta, "meta.social_intolerance_biv.csv"))
socintol.effects     <- read_if(paste0(base_path_effects, "22.results_socialintolerance_models.csv"))

# Authoritarianism
meta.autho        <- read_if(paste0(base_path_meta, "meta.authoritarian.csv"))
meta.autho.random <- read_if(paste0(base_path_meta, "meta.authoritarian_random.csv"))
meta.autho_biv    <- read_if(paste0(base_path_meta, "meta.authoritarian_biv.csv"))
autho.effects     <- read_if(paste0(base_path_effects, "16.results_authoritarian_models.csv"))

# Institutional mistrust
meta.institutional        <- read_if(paste0(base_path_meta, "meta.instmistrust.csv"))
meta.institutional.random <- read_if(paste0(base_path_meta, "meta.instmistrust_random.csv"))
meta.institutional_biv    <- read_if(paste0(base_path_meta, "meta.instmistrust_biv.csv"))
institutional.effects     <- read_if(paste0(base_path_effects, "19.results_instmistrust_models.csv"))

# Hawkish security preferences
meta.security        <- read_if(paste0(base_path_meta, "meta.hawkish.csv"))
meta.security.random <- read_if(paste0(base_path_meta, "meta.hawkish_random.csv"))
meta.security_biv    <- read_if(paste0(base_path_meta, "meta.hawkish_biv.csv"))
security.effects     <- read_if(paste0(base_path_effects, "18.results_hawkish_models.csv"))

# Support for punitive justice
meta.punitive        <- read_if(paste0(base_path_meta, "meta.punitive.csv"))
meta.punitive.random <- read_if(paste0(base_path_meta, "meta.punitive_random.csv"))
meta.punitive_biv    <- read_if(paste0(base_path_meta, "meta.punitive_biv.csv"))
punitive.effects     <- read_if(paste0(base_path_effects, "21.results_punitive_models.csv"))

# Antagonism toward peace  [included here, you can omit from the final stack if you want 7 rows]
meta.antipeace        <- read_if(paste0(base_path_meta, "meta.antipeace.csv"))
meta.antipeace.random <- read_if(paste0(base_path_meta, "meta.antipeace_random.csv"))
meta.antipeace_biv    <- read_if(paste0(base_path_meta, "meta.antipeace_biv.csv"))
antipeace.effects     <- read_if(paste0(base_path_effects, "15.results_antipeace_models.csv"))

# Extreme ideology
meta.xtr        <- read_if(paste0(base_path_meta, "meta.xtrideology.csv"))
meta.xtr.random <- read_if(paste0(base_path_meta, "meta.xtrideology_random.csv"))
meta.xtr_biv    <- read_if(paste0(base_path_meta, "meta.xtrideology_biv.csv"))
xtr.effects     <- read_if(paste0(base_path_effects, "17.results_xtrideology_models.csv"))

# Stack effects
re3_estimates <- bind_rows(
  polintol.effects, socintol.effects, autho.effects, institutional.effects,
  security.effects, punitive.effects, antipeace.effects, xtr.effects
)

## ======================== PLOTS, ONE BLOCK PER OUTCOME ========================

## Political intolerance
origN <- n_distinct(meta.polintol$authoryear); origK <- nrow(meta.polintol)
qeN   <- 0
qeK   <- 0

pd_polintol <- re3_estimates %>%
  filter(tolower(outcome) == "political intolerance") %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

polintol.plot <- ggplot(meta.polintol, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.polintol_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_polintol, aes(x = coef, y = y, color = col),
             shape = pd_polintol$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_polintol, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_polintol, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Political\nintolerance") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Social intolerance
origN <- n_distinct(meta.socintol$authoryear); origK <- nrow(meta.socintol)
qeN   <- if (is.null(meta.socintol.random)) 0 else n_distinct(meta.socintol.random$authoryear)
qeK   <- if (is.null(meta.socintol.random)) 0 else nrow(meta.socintol.random)

pd_socintol <- re3_estimates %>%
  filter(tolower(outcome) == "social intolerance") %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

socintol.plot <- ggplot(meta.socintol, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.socintol_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_socintol, aes(x = coef, y = y, color = col),
             shape = pd_socintol$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_socintol, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_socintol, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Social\nintolerance") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Authoritarianism
origN <- n_distinct(meta.autho$authoryear); origK <- nrow(meta.autho)
qeN   <- if (is.null(meta.autho.random)) 0 else n_distinct(meta.autho.random$authoryear)
qeK   <- if (is.null(meta.autho.random)) 0 else nrow(meta.autho.random)

pd_autho <- re3_estimates %>%
  filter(tolower(outcome) %in% c("authoritarian attitudes","authoritarianism")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

autho.plot <- ggplot(meta.autho, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.autho_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_autho, aes(x = coef, y = y, color = col),
             shape = pd_autho$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_autho, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_autho, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Authoritarian\nattitudes") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Institutional mistrust
origN <- n_distinct(meta.institutional$authoryear); origK <- nrow(meta.institutional)
qeN   <- if (is.null(meta.institutional.random)) 0 else n_distinct(meta.institutional.random$authoryear)
qeK   <- if (is.null(meta.institutional.random)) 0 else nrow(meta.institutional.random)

pd_institutional <- re3_estimates %>%
  filter(tolower(outcome) %in% c("institutional distrust","institutional mistrust")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

institutional.plot <- ggplot(meta.institutional, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.institutional_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_institutional, aes(x = coef, y = y, color = col),
             shape = pd_institutional$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_institutional, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_institutional, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Institutional\nmistrust") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Hawkish security preferences
origN <- n_distinct(meta.security$authoryear); origK <- nrow(meta.security)
qeN   <- if (is.null(meta.security.random)) 0 else n_distinct(meta.security.random$authoryear)
qeK   <- if (is.null(meta.security.random)) 0 else nrow(meta.security.random)

pd_security <- re3_estimates %>%
  filter(tolower(outcome) %in% c("security preferences","hawkish security preferences","hawkish preferences","hawkish")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

security.plot <- ggplot(meta.security, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.security_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_security, aes(x = coef, y = y, color = col),
             shape = pd_security$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_security, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_security, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Hawkish\nsecurity\npreferences") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Support for punitive justice
origN <- n_distinct(meta.punitive$authoryear); origK <- nrow(meta.punitive)
qeN   <- if (is.null(meta.punitive.random)) 0 else n_distinct(meta.punitive.random$authoryear)
qeK   <- if (is.null(meta.punitive.random)) 0 else nrow(meta.punitive.random)

pd_punitive <- re3_estimates %>%
  filter(tolower(outcome) %in% c("support for punitive justice","punitive justice","punitive attitudes","punitive")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

punitive.plot <- ggplot(meta.punitive, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.punitive_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_punitive, aes(x = coef, y = y, color = col),
             shape = pd_punitive$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_punitive, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_punitive, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Support for\npunitive\njustice") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Antagonism toward peace
origN <- n_distinct(meta.antipeace$authoryear); origK <- nrow(meta.antipeace)
qeN   <- if (is.null(meta.antipeace.random)) 0 else n_distinct(meta.antipeace.random$authoryear)
qeK   <- if (is.null(meta.antipeace.random)) 0 else nrow(meta.antipeace.random)

pd_antipeace <- re3_estimates %>%
  filter(tolower(outcome) %in% c("antagonism toward peace","antipeace")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

antipeace.plot <- ggplot(meta.antipeace, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.antipeace_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_antipeace, aes(x = coef, y = y, color = col),
             shape = pd_antipeace$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_antipeace, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_antipeace, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "Effect size", y = "Antagonism\ntoward\npeace") +
  theme_minimal() +
  theme(
    axis.title.x = element_text(size = 10, face = "bold"),
    axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
    axis.text.y = element_blank(), axis.ticks.y = element_blank(),
    panel.grid = element_blank(),
    plot.margin = margin(0,0,0,0), legend.position = "none"
  ) +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## Extreme ideology
origN <- n_distinct(meta.xtr$authoryear); origK <- nrow(meta.xtr)
qeN   <- if (is.null(meta.xtr.random)) 0 else n_distinct(meta.xtr.random$authoryear)
qeK   <- if (is.null(meta.xtr.random)) 0 else nrow(meta.xtr.random)

pd_xtr <- re3_estimates %>%
  filter(tolower(outcome) %in% c("extreme ideology","extremist ideology")) %>%
  transmute(
    sample_model = paste(model_type, sample_type, sep = " - "),
    coef, ci.lb95, ci.ub95, pval,
    y = case_when(
      sample_model == "Bivariate - All" ~ 1.000,
      sample_model %in% c("Full - All", "Original - All") ~ 1.012,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ 0.988,
      TRUE ~ NA_real_
    ),
    col = case_when(
      sample_model == "Bivariate - All" ~ col_biv,
      sample_model %in% c("Full - All", "Original - All") ~ col_full,
      sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental") ~ col_qe,
      TRUE ~ NA_character_
    ),
    shp = ifelse(sample_model %in% c("Full - Quasi-experimental", "Original - Quasi-experimental"), sh_qe, sh_full),
    lab = lbl(coef, pval)
  ) %>% tidyr::drop_na(y)

xtr.plot <- ggplot(meta.xtr, aes(x = coef, y = 1, size = 1 / se)) +
  geom_jitter(shape = 21, fill = "gray70", color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_jitter(data = meta.xtr_biv, aes(x = coef, y = 1, size = 1 / se),
              shape = 4, stroke = 1, color = "gray70", alpha = .3, width = 0, height = .012) +
  geom_point(data = pd_xtr, aes(x = coef, y = y, color = col),
             shape = pd_xtr$shp, size = 2.6, stroke = 1.5, fill = "white") +
  geom_errorbarh(data = pd_xtr, aes(y = y, xmin = ci.lb95, xmax = ci.ub95, color = col),
                 height = 0, size = .9) +
  geom_text(data = pd_xtr, aes(x = coef, y = y + .005, label = lab, color = col),
            size = 3, fontface = "bold") +
  scale_color_identity() + scale_size_continuous(range = c(1,10), guide = "none") +
  labs(x = "", y = "Extreme\nideology") +
  theme_void() +
  theme(axis.title.y = element_text(angle = 90, size = 10, face = "bold"),
        plot.margin = margin(0,0,0,0), legend.position = "none") +
  xlim(c(-.4,.4)) + ylim(c(.985,1.025)) +
  ggplot2::annotate("text", x = .30, y = 1.000, label = paste0("All:\nN = ", origN, "\nk = ", origK), size = 3) +
  ggplot2::annotate("text", x = .40, y = 1.000, label = paste0("QE:\nN = ", qeN,   "\nk = ", qeK), size = 3)

## ------------------------ Legend and export ------------------------
legend_plot <- ggplot() +
  xlim(0, 1) + ylim(0, 1) + theme_void() +
  ggplot2::annotate("point", x = 0.70, y = 0.90, shape = sh_full, size = 3, color = col_full, fill = col_full) +
  ggplot2::annotate("text",  x = 0.73, y = 0.90, label = "Full models", hjust = 0, vjust = 0.5, size = 3) +
  ggplot2::annotate("point", x = 0.70, y = 0.70, shape = sh_biv,  size = 3, color = col_biv,  fill = col_biv) +
  ggplot2::annotate("text",  x = 0.73, y = 0.70, label = "Bivariate models", hjust = 0, vjust = 0.5, size = 3) +
  ggplot2::annotate("point", x = 0.70, y = 0.50, shape = sh_qe,   size = 3, color = col_qe,  fill = col_qe) +
  ggplot2::annotate("text",  x = 0.73, y = 0.50, label = "Quasi experimental models", hjust = 0, vjust = 0.5, size = 3) +
  theme(plot.margin = unit(c(0, 0, 0, 0), "cm")) +
  labs(x = "", y = "")

Figure4 <- (
    autho.plot /
    institutional.plot /
    security.plot /
    polintol.plot /
    socintol.plot /
    punitive.plot /
    xtr.plot /
    antipeace.plot /
    legend_plot
) & theme(axis.title.x = element_text(face = "bold")) & plot_layout(guides = "collect")

out_path <- "/Users/jbs548/Library/CloudStorage/Dropbox/Joan Barcelo/Present/NYUAD Assistant Professor/Research/Papers/Work in Progress/Meta_analysis/Analysis/Replication_materials_APSR/Figures/"
pdf(paste0(out_path, "Figure4.pdf"), height = 16, width = 8.4, paper = "letter")
print(Figure4)
grid.draw(linesGrob(x = unit(c(0.527, 0.527), "npc"),
                    y = unit(c(0.16, 1.00), "npc"),
                    gp = gpar(col = "darkgray", alpha = 0.4)))
dev.off()
